﻿using Autofac;
using Autofac.Extensions.DependencyInjection;
using HealthChecks.UI.Client;
using Identity.Api.Data;
using Identity.Api.Devspaces;
using Identity.Api.Models;
using Identity.Api.Services;
using Identity.API;
using IdentityServer4.Services;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using StackExchange.Redis;
using System.Reflection;
namespace Identity.Api
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            #region 注册DbContext
            var connectionString = Configuration["ConnectionString"];
            var migrationsAssembly = typeof(Program).GetTypeInfo().Assembly.GetName().Name;

            services.AddDbContext<ApplicationDbContext>(options =>
            options.UseMySql(connectionString, new MySqlServerVersion(new Version(5, 7, 28)), mySqlOptions =>
            {
                mySqlOptions.MigrationsAssembly(migrationsAssembly);
                mySqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
                mySqlOptions.CommandTimeout(300);
            }));
            #endregion

            #region Register Identity
            services.AddIdentity<ApplicationUser, IdentityRole>()
                         .AddEntityFrameworkStores<ApplicationDbContext>()
                         .AddDefaultTokenProviders();
            #endregion

            #region Env
            services.Configure<AppSettings>(Configuration);
            #endregion

            #region 敏感数据加密

            if (Configuration.GetValue<string>("IsClusterEnv") == bool.TrueString)
            {
                services.AddDataProtection(opts =>
                {
                    opts.ApplicationDiscriminator = "eshop.identity";
                })
                .PersistKeysToStackExchangeRedis(ConnectionMultiplexer.Connect(Configuration["DPConnectionString"]), "DataProtection-Keys");
            }
            #endregion

            #region Health Mysql

            services.AddHealthChecks()
                         .AddCheck("self", () => HealthCheckResult.Healthy())
                         .AddMySql(connectionString, name: "IdentityDB-check", tags: new string[] { "IdentityDB" });
            #endregion

            #region 自定义服务注册
            services.AddTransient<ILoginService<ApplicationUser>, EFLoginService>();
            services.AddTransient<IRedirectService, RedirectService>();
            #endregion

            #region IdentityServer 数据库加载模式
            services.AddIdentityServer(x =>
            {
                x.IssuerUri = "null";
                x.Authentication.CookieLifetime = TimeSpan.FromHours(2);
            })
                     .AddDevspacesIfNeeded(Configuration.GetValue("EnableDevspaces", false))
                     //.AddSigningCredential(Certificate.Certificate.Get())//本地证书测试使用
                     .AddDeveloperSigningCredential()//开放环境应用即时证书
                     .AddAspNetIdentity<ApplicationUser>()
                     .AddValidators()
                     .AddConfigurationStore(options =>
                     {
                         options.ConfigureDbContext = builder => builder.UseMySql(connectionString, new MySqlServerVersion(new Version(5, 7, 28)), mySqlOptions =>
                         {
                             mySqlOptions.MigrationsAssembly(migrationsAssembly);
                             mySqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
                             mySqlOptions.CommandTimeout(300);
                         });
                     })
                     .AddOperationalStore(options =>
                     {
                         options.ConfigureDbContext = builder => builder.UseMySql(connectionString, new MySqlServerVersion(new Version(5, 7, 28)), mySqlOptions =>
                         {
                             mySqlOptions.MigrationsAssembly(migrationsAssembly);
                             mySqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
                             mySqlOptions.CommandTimeout(300);
                         });
                         options.EnableTokenCleanup = true;//自动从数据库清除过时条目
                         options.TokenCleanupInterval = 3600;

                     })
                     .Services.AddTransient<IProfileService, ProfileService>();
            #endregion

            #region Mvc
            services.AddControllers();
            services.AddControllersWithViews();
            #endregion

            #region Autofac
            var container = new ContainerBuilder();
            container.Populate(services);

            return new AutofacServiceProvider(container.Build());

            #endregion
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            var pathBase = Configuration["PATH_BASE"];
            if (!string.IsNullOrEmpty(pathBase))
            {
                app.UsePathBase(pathBase);
            }

            app.UseStaticFiles();

            //使工作身份服务器重定向在edge和最新版本的浏览器。警告: 在生产环境中无效
            app.Use(async (context, next) =>
            {
                context.Response.Headers.Add("Content-Security-Policy", "script-src 'unsafe-inline'");
                await next();
            });
            // 转发标头
            app.UseForwardedHeaders();
            // 添加 IdentityServer4 服务中间件
            app.UseIdentityServer();
            app.UseAuthentication();
            app.UseAuthorization();
            app.UseCookiePolicy(new CookiePolicyOptions { MinimumSameSitePolicy = SameSiteMode.Lax });
            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapDefaultControllerRoute();
                endpoints.MapControllers();
                endpoints.MapHealthChecks("/hc", new HealthCheckOptions()
                {
                    Predicate = _ => true,
                    ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
                });
                endpoints.MapHealthChecks("/liveness", new HealthCheckOptions
                {
                    Predicate = r => r.Name.Contains("self")
                });
            });

        }

    }
}
